/**
 * pecker.h - Main header for the woodpecker plugin.
 *
 * Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.edu>
 * Copyright (C) 2008, The WoodPecker Team
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * $Id: pecker.h 128 2008-04-13 01:34:40Z dubkat $
 */

#define PURPLE_WEBSITE "http://www.pidgin.im"
#ifndef _PURPLE_PECKER_H
#define _PURPLE_PECKER_H

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef _WIN32
/* blah */
#else
#include <glib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#endif /* end win32 */

#include <roomlist.h>
#include <util.h>

#define PECKER_USER_AGENT "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13"
#define IRC_DEFAULT_SERVER "www.gay.com"
#define IRC_DEFAULT_PORT 7514
#define IRC_DEFAULT_CHARSET "UTF-8"
#define IRC_DEFAULT_ALIAS "purple"
#define IRC_INITIAL_BUFSIZE 1024
#define BLIST_UPDATE_PERIOD 60000       /* buddy list updated every 45s */
#define BLIST_CHUNK_INTERVAL 5000       /* 5s between ISON chunks */
#define MAX_BIO_LEN 150         /* max number of characters in bio */
#define MAX_CHANNEL_MEMBERS 200
#define PECKER_STATUS_ID_AWAY "away"
#define PECKER_STATUS_ID_AVAILABLE "available"
#define PECKER_STATUS_ID_OFFLINE "offline"
#define PIDGIN_PREFS_ROOT "/pidgin"

typedef struct _BListWhois BListWhois;
struct _BListWhois
{
    int count;
    GString *string;
};

enum
{
    IRC_USEROPT_SERVER,
    IRC_USEROPT_PORT,
    IRC_USEROPT_CHARSET
};

enum pecker_state
{
    IRC_STATE_NEW,
    IRC_STATE_ESTABLISHED
};

enum info_string
{
    INFO_AGE,
    INFO_LOCATION,
    INFO_BIO,
    INFO_URL
};

struct pecker_conn
{
    PurpleAccount *account;
    GHashTable *msgs;
    GHashTable *cmds;
    char *server;
    int fd;
    guint timer;
    GHashTable *buddies;        /* hash table of struct pecker_buddy */
    GHashTable *channel_members;        /* hash table of struct pecker_buddy */

    char *inbuf;
    int inbuflen;
    int inbufused;

    char *thumbnail;
    char *chat_key;
    char *server_bioline;
    char *server_stats;
    char *roomlist_filter;
    char *bio;

    gboolean blist_updating;
    GHashTable *info_window_needed;

    GString *motd;
    GString *names;
    char *nameconv;
    char *traceconv;

    PurpleRoomlist *roomlist;

    GList **node_menu;
    gboolean quitting;
    char *subroom;
    GHashTable *confighash;
    GHashTable *entry_order;

    GHashTable *hammers;

    /* Namelists come in order so use a queue. */
    GQueue *namelists;

};

typedef struct
{

    gchar *cookies;
    GHashTable *cookie_table;
    void (*session_cb) (PurpleAccount *);
    PurpleAccount *account;
    char *username;
    char *password;
    struct pecker_conn *pecker;
    gboolean hasFormData;

} PurpleUrlSession;


typedef struct pecker_buddy PeckerBuddy;
struct pecker_buddy
{
    gchar *name;                /* pecker formatted nick */
    gboolean done;              /* has been checked */
    gboolean online;            /* is online */
    gint ref_count;             /* reference count for mem mngmnt */
    gchar *bio;                 /* bio string */
    gchar *thumbnail;           /* thumbnail string */
    gchar *sex;                 /* sex string */
    gchar *age;                 /* age string */
    gchar *prefix;              /* prefix string */
    gchar *location;            /* location string */
    gchar *room;                /* Which subroom, if this is a namelist entry */
    gboolean peckeruser;        /* gay.com detected */
};


PeckerBuddy *pecker_get_channel_member_info(struct pecker_conn *pecker, const gchar * name);
PeckerBuddy *pecker_get_channel_member_reference(struct pecker_conn *pecker, const char *name);

gboolean pecker_unreference_channel_member(struct pecker_conn *pecker, gchar * name);

struct hammer_cb_data
{
    struct pecker_conn *pecker;
    char *room;
    void *cancel_dialog;
} hammer_cb_data;

struct get_info_data
{
    const char *who;
    char *stats;
    char *bio;
    PurpleNotifyUserInfo *info;
    struct pecker_conn *pecker;
    PurpleConnection *gc;
} get_info_data;

void hammer_cb_data_destroy(struct hammer_cb_data *hdata);
void close_info_cb(gpointer cb_data);
typedef int (*IRCCmdCallback) (struct pecker_conn * pecker, const char *cmd, const char *target, const char **args);

int pecker_send(struct pecker_conn *pecker, const char *buf);
gboolean pecker_blist_timeout(struct pecker_conn *pecker);

char *pecker_mpecker2html(const char *string);
char *pecker_mpecker2txt(const char *string);

void pecker_register_commands(void);
void pecker_msg_table_build(struct pecker_conn *pecker);
void pecker_parse_msg(struct pecker_conn *pecker, char *input);
char *pecker_parse_ctcp(struct pecker_conn *pecker, const char *from, const char *to, const char *msg, int notice);
char *pecker_format(struct pecker_conn *pecker, const char *format, ...);

typedef void (msg_handler) (struct pecker_conn * pecker, const char *name, const char *from, char **args);
msg_handler pecker_msg_away;
msg_handler pecker_msg_default;
msg_handler pecker_msg_away;
msg_handler pecker_msg_badmode;
msg_handler pecker_msg_banned;
msg_handler pecker_msg_chanmode;
msg_handler pecker_msg_endwhois;
msg_handler pecker_msg_endmotd;
msg_handler pecker_msg_invite;
msg_handler pecker_msg_inviteonly;
msg_handler pecker_msg_who;
msg_handler pecker_msg_chanfull;
msg_handler pecker_msg_join;
msg_handler pecker_msg_kick;
msg_handler pecker_msg_list;
msg_handler pecker_msg_login_failed;
msg_handler pecker_msg_mode;
msg_handler pecker_msg_motd;
msg_handler pecker_msg_names;
msg_handler pecker_msg_nick;
msg_handler pecker_msg_nickused;
msg_handler pecker_msg_nochan;
msg_handler pecker_msg_nonick_chan;
msg_handler pecker_msg_nonick;
msg_handler pecker_msg_no_such_nick;
msg_handler pecker_msg_nochangenick;
msg_handler pecker_msg_nosend;
msg_handler pecker_msg_notice;
msg_handler pecker_msg_notinchan;
msg_handler pecker_msg_notop;
msg_handler pecker_msg_part;
msg_handler pecker_msg_ping;
msg_handler pecker_msg_pong;
msg_handler pecker_msg_privmsg;
msg_handler pecker_msg_regonly;
msg_handler pecker_msg_quit;
msg_handler pecker_msg_topic;
msg_handler pecker_msg_trace;
msg_handler pecker_msg_unknown;
msg_handler pecker_msg_wallops;
msg_handler pecker_msg_whois;
msg_handler pecker_msg_richnames_list;
msg_handler pecker_msg_create_pay_only;
msg_handler pecker_msg_pay_channel;
msg_handler pecker_msg_toomany_channels;
msg_handler pecker_msg_list_busy;


void pecker_cmd_table_build(struct pecker_conn *pecker);

typedef int (cmd_handler) (struct pecker_conn * pecker, const char *cmd, const char *target, const char **args);

cmd_handler pecker_cmd_away;
cmd_handler pecker_cmd_ctcp_action;
cmd_handler pecker_cmd_join;
cmd_handler pecker_cmd_list;
cmd_handler pecker_cmd_nick;
cmd_handler pecker_cmd_privmsg;
cmd_handler pecker_cmd_part;
cmd_handler pecker_cmd_ping;
cmd_handler pecker_cmd_quit;
cmd_handler pecker_cmd_quote;
cmd_handler pecker_cmd_query;
cmd_handler pecker_cmd_remove;
cmd_handler pecker_cmd_trace;
cmd_handler pecker_cmd_whois;
cmd_handler pecker_cmd_who;
cmd_handler pecker_cmd_invite;
cmd_handler pecker_cmd_info;


/**
 * these are disabled, pretty much useless commands.
 **

cmd_handler pecker_cmd_default;
cmd_handler pecker_cmd_kick;
cmd_handler pecker_cmd_mode;
cmd_handler pecker_cmd_op;
cmd_handler pecker_cmd_topic;
cmd_handler pecker_cmd_wallops;
cmd_handler pecker_cmd_names;


*/

typedef struct PeckerNamelist
{
    char *roomname;
    GSList *members;            // List of PeckerBuddies;
    int num_rooms;
    gboolean multi_room;
    GSList *current;            // Pointer to peckerbuddy to be updated next 
    // 
    // 
    // (during names pass)
} PeckerNamelist;


void pecker_get_chat_key_from_weblogin(PurpleAccount * account, void (*callback) (PurpleAccount *));
void pecker_get_room_namelist(PurpleAccount * account, const char *room);
int gethostname(char *name, size_t size);

PurpleUtilFetchUrlData *pecker_util_fetch_url_request(const char *url, gboolean full, const char *user_agent, gboolean http11,
                                                      const char *request, gboolean include_headers,
                                                      PurpleUtilFetchUrlCallback callback, void *user_data);

#endif /* _PURPLE_PECKER_H */
